package com.ecommerce.chat.service;

import com.alibaba.fastjson.JSON;
import com.ecommerce.chat.config.ChatConfig;
import com.ecommerce.chat.dto.*;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;

/**
 * AI客服服务类
 * 负责与DeepSeek API交互，提供智能客服功能
 */
@Slf4j
@Service
public class ChatService {
    
    @Autowired
    private ChatConfig chatConfig;
    
    @Autowired
    private OkHttpClient okHttpClient;
    
    /**
     * 异步执行器
     */
    private final Executor asyncExecutor = Executors.newFixedThreadPool(10);
    
    /**
     * 会话上下文缓存
     * Key: sessionId, Value: 消息历史
     */
    private final ConcurrentHashMap<String, List<ChatMessage>> sessionCache = new ConcurrentHashMap<>();
    
    /**
     * 响应缓存
     * Key: 问题的MD5哈希, Value: AI回复
     */
    private final ConcurrentHashMap<String, String> responseCache = new ConcurrentHashMap<>();
    
    /**
     * 处理聊天请求（异步）
     * 
     * @param request 聊天请求
     * @return 聊天响应的CompletableFuture
     */
    public CompletableFuture<ChatResponse> chatAsync(ChatRequest request) {
        return CompletableFuture.supplyAsync(() -> {
            return processChat(request);
        }, asyncExecutor);
    }
    
    /**
     * 处理聊天请求（同步）
     * 
     * @param request 聊天请求
     * @return 聊天响应
     */
    public ChatResponse chat(ChatRequest request) {
        return processChat(request);
    }
    
    /**
     * 处理聊天请求的核心逻辑
     * 
     * @param request 聊天请求
     * @return 聊天响应
     */
    private ChatResponse processChat(ChatRequest request) {
        long startTime = System.currentTimeMillis();
        try {
            // 参数验证
            if (!StringUtils.hasText(request.getMessage())) {
                return ChatResponse.error("消息内容不能为空", request.getSessionId());
            }
            
            // 生成或获取会话ID
            String sessionId = StringUtils.hasText(request.getSessionId()) 
                    ? request.getSessionId() 
                    : generateSessionId();
            
            // 检查缓存
            String cacheKey = generateCacheKey(request.getMessage());
            String cachedResponse = responseCache.get(cacheKey);
            if (cachedResponse != null) {
                long responseTime = System.currentTimeMillis() - startTime;
                log.info("缓存命中，响应时间: {}ms", responseTime);
                return ChatResponse.success(cachedResponse, sessionId);
            }
            
            // 构建消息列表
            List<ChatMessage> messages = buildMessages(sessionId, request.getMessage());
            
            // 调用DeepSeek API
            DeepSeekResponse deepSeekResponse = callDeepSeekAPI(messages);
            
            // 处理响应
            if (deepSeekResponse != null && deepSeekResponse.getChoices() != null && !deepSeekResponse.getChoices().isEmpty()) {
                String reply = deepSeekResponse.getChoices().get(0).getMessage().getContent();
                
                // 缓存响应（对于常见问题）
                if (isCommonQuestion(request.getMessage())) {
                    responseCache.put(cacheKey, reply);
                    log.debug("缓存响应: {}", cacheKey);
                }
                
                // 更新会话缓存
                updateSessionCache(sessionId, request.getMessage(), reply);
                
                // 构建响应
                ChatResponse response = ChatResponse.success(reply, sessionId);
                
                // 设置Token使用情况
                if (deepSeekResponse.getUsage() != null) {
                    response.setTokenUsage(ChatResponse.TokenUsage.builder()
                            .inputTokens(deepSeekResponse.getUsage().getPromptTokens())
                            .outputTokens(deepSeekResponse.getUsage().getCompletionTokens())
                            .totalTokens(deepSeekResponse.getUsage().getTotalTokens())
                            .build());
                }
                
                // 记录响应时间
                long responseTime = System.currentTimeMillis() - startTime;
                log.info("聊天请求处理完成，响应时间: {}ms, Token使用: {}", 
                        responseTime, 
                        deepSeekResponse.getUsage() != null ? deepSeekResponse.getUsage().getTotalTokens() : 0);
                
                return response;
            } else {
                log.error("DeepSeek API返回空响应");
                return ChatResponse.error("AI服务暂时不可用，请稍后重试", sessionId);
            }
            
        } catch (Exception e) {
            log.error("处理聊天请求失败", e);
            return ChatResponse.error("服务异常，请稍后重试", request.getSessionId());
        }
    }
    
    /**
     * 调用DeepSeek API
     * 
     * @param messages 消息列表
     * @return API响应
     */
    private DeepSeekResponse callDeepSeekAPI(List<ChatMessage> messages) {
        int retryCount = 0;
        Exception lastException = null;
        
        while (retryCount < chatConfig.getMaxRetries()) {
            try {
                // 构建请求体
                DeepSeekRequest deepSeekRequest = DeepSeekRequest.builder()
                        .messages(messages)
                        .build();
                
                String requestBody = JSON.toJSONString(deepSeekRequest);
                log.debug("DeepSeek API请求: {}", requestBody);
                
                // 构建HTTP请求
                Request request = new Request.Builder()
                        .url(chatConfig.getApiUrl())
                        .post(RequestBody.create(requestBody, MediaType.parse("application/json")))
                        .addHeader("Content-Type", "application/json")
                        .addHeader("Authorization", "Bearer " + chatConfig.getApiKey())
                        .build();
                
                // 发送请求
                try (Response response = okHttpClient.newCall(request).execute()) {
                    if (response.isSuccessful() && response.body() != null) {
                        String responseBody = response.body().string();
                        log.debug("DeepSeek API响应: {}", responseBody);
                        
                        return JSON.parseObject(responseBody, DeepSeekResponse.class);
                    } else {
                        String errorBody = response.body() != null ? response.body().string() : "";
                        log.error("DeepSeek API请求失败，状态码: {}, 响应: {}", response.code(), errorBody);
                        throw new RuntimeException("API请求失败: " + response.code());
                    }
                }
                
            } catch (Exception e) {
                lastException = e;
                retryCount++;
                log.warn("DeepSeek API调用失败，重试次数: {}/{}", retryCount, chatConfig.getMaxRetries(), e);
                
                if (retryCount < chatConfig.getMaxRetries()) {
                    try {
                        Thread.sleep(1000 * retryCount); // 指数退避
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
        
        log.error("DeepSeek API调用最终失败", lastException);
        throw new RuntimeException("AI服务调用失败", lastException);
    }
    
    /**
     * 构建消息列表
     * 
     * @param sessionId 会话ID
     * @param userMessage 用户消息
     * @return 消息列表
     */
    private List<ChatMessage> buildMessages(String sessionId, String userMessage) {
        List<ChatMessage> messages = new ArrayList<>();
        
        // 添加系统提示词
        messages.add(ChatMessage.system(chatConfig.getSystemPrompt()));
        
        // 添加历史消息（限制数量以提升性能）
        List<ChatMessage> history = sessionCache.get(sessionId);
        if (history != null && !history.isEmpty()) {
            // 只保留最近的6条消息（3轮对话）
            int maxHistorySize = 6;
            int startIndex = Math.max(0, history.size() - maxHistorySize);
            messages.addAll(history.subList(startIndex, history.size()));
        }
        
        // 添加当前用户消息
        messages.add(ChatMessage.user(userMessage));
        
        return messages;
    }
    
    /**
     * 更新会话缓存
     * 
     * @param sessionId 会话ID
     * @param userMessage 用户消息
     * @param aiReply AI回复
     */
    private void updateSessionCache(String sessionId, String userMessage, String aiReply) {
        List<ChatMessage> history = sessionCache.computeIfAbsent(sessionId, k -> new ArrayList<>());
        
        // 添加用户消息和AI回复
        history.add(ChatMessage.user(userMessage));
        history.add(ChatMessage.assistant(aiReply));
        
        // 限制会话历史长度，避免内存占用过大
        int maxCacheSize = 20; // 最多保留10轮对话
        if (history.size() > maxCacheSize) {
            // 移除最早的消息，保留最新的对话
            history.subList(0, history.size() - maxCacheSize).clear();
        }
    }
    
    /**
     * 生成会话ID
     * 
     * @return 会话ID
     */
    private String generateSessionId() {
        return "session_" + UUID.randomUUID().toString().replace("-", "");
    }
    
    /**
     * 清除会话缓存
     * 
     * @param sessionId 会话ID
     */
    public void clearSession(String sessionId) {
        if (StringUtils.hasText(sessionId)) {
            sessionCache.remove(sessionId);
            log.info("已清除会话缓存: {}", sessionId);
        }
    }
    
    /**
     * 获取会话消息数量
     * 
     * @param sessionId 会话ID
     * @return 消息数量
     */
    public int getSessionMessageCount(String sessionId) {
        List<ChatMessage> history = sessionCache.get(sessionId);
        return history != null ? history.size() : 0;
    }
    
    /**
     * 生成缓存键
     * 
     * @param message 消息内容
     * @return 缓存键
     */
    private String generateCacheKey(String message) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(message.toLowerCase().trim().getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : hash) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            log.warn("生成缓存键失败", e);
            return message.hashCode() + "";
        }
    }
    
    /**
     * 判断是否为常见问题
     * 
     * @param message 消息内容
     * @return 是否为常见问题
     */
    private boolean isCommonQuestion(String message) {
        String lowerMessage = message.toLowerCase().trim();
        // 定义常见问题关键词 - 扩展版
        String[] commonKeywords = {
            // 问候语
            "你好", "hello", "hi", "帮助", "help", "在吗", "客服",
            // 售后服务
            "退货", "退款", "换货", "发货", "物流", "快递", "配送", "收货", "签收",
            // 价格相关
            "价格", "多少钱", "优惠", "折扣", "活动", "促销", "便宜", "贵", "划算",
            // 商品信息
            "尺码", "大小", "颜色", "材质", "规格", "型号", "品牌", "质量", "重量",
            // 购买流程
            "支付", "付款", "订单", "购买", "下单", "库存", "现货", "预售",
            // 账户相关
            "登录", "注册", "密码", "账号", "会员", "积分", "余额",
            // 常见问题
            "怎么", "如何", "什么", "哪里", "为什么", "可以", "能不能", "有没有",
            // 时间相关
            "什么时候", "多久", "几天", "营业时间", "工作时间"
        };
        
        for (String keyword : commonKeywords) {
            if (lowerMessage.contains(keyword)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 清除响应缓存
     */
    public void clearResponseCache() {
        responseCache.clear();
        log.info("AI客服响应缓存已清除");
    }

    /**
     * 流式聊天处理
     */
    public void streamChat(ChatRequest request, SseEmitter emitter) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 参数验证
            if (request == null || !StringUtils.hasText(request.getMessage())) {
                emitter.send(SseEmitter.event()
                    .name("error")
                    .data("消息内容不能为空"));
                emitter.complete();
                return;
            }

            String sessionId = StringUtils.hasText(request.getSessionId()) ? 
                request.getSessionId() : generateSessionId();

            // 检查缓存
            String cacheKey = generateCacheKey(request.getMessage());
            String cachedResponse = responseCache.get(cacheKey);
            
            if (cachedResponse != null) {
                long responseTime = System.currentTimeMillis() - startTime;
                log.info("缓存命中，响应时间: {}ms", responseTime);
                
                // 模拟流式输出缓存内容
                String[] words = cachedResponse.split("");
                for (int i = 0; i < words.length; i++) {
                    emitter.send(SseEmitter.event()
                        .name("data")
                        .data(words[i]));
                    
                    // 模拟打字效果
                    if (i % 5 == 0) {
                        Thread.sleep(50);
                    }
                }
                
                emitter.send(SseEmitter.event()
                    .name("end")
                    .data("complete"));
                emitter.complete();
                return;
            }

            // 发送开始事件
            emitter.send(SseEmitter.event()
                .name("start")
                .data("开始生成回复..."));

            // 调用AI API并流式输出
            String fullResponse = callDeepSeekAPIForStream(request, emitter);
            
            if (fullResponse != null && !fullResponse.isEmpty()) {
                // 缓存响应
                if (isCommonQuestion(request.getMessage())) {
                    responseCache.put(cacheKey, fullResponse);
                }
                
                // 更新会话上下文
                updateSessionCache(sessionId, request.getMessage(), fullResponse);
                
                long responseTime = System.currentTimeMillis() - startTime;
                log.info("流式聊天完成，总响应时间: {}ms", responseTime);
            }
            
            emitter.send(SseEmitter.event()
                .name("end")
                .data("complete"));
            emitter.complete();
            
        } catch (Exception e) {
            log.error("流式聊天处理失败", e);
            try {
                emitter.send(SseEmitter.event()
                    .name("error")
                    .data("处理失败: " + e.getMessage()));
                emitter.completeWithError(e);
            } catch (IOException ioException) {
                log.error("发送错误事件失败", ioException);
                emitter.completeWithError(ioException);
            }
        }
    }
    
    /**
     * 调用DeepSeek API进行流式输出
     * 
     * @param request 聊天请求
     * @param emitter SSE发射器
     * @return 完整响应内容
     */
    private String callDeepSeekAPIForStream(ChatRequest request, SseEmitter emitter) throws IOException {
        // 构建消息列表
        String sessionId = StringUtils.hasText(request.getSessionId()) ? 
            request.getSessionId() : generateSessionId();
        List<ChatMessage> messages = buildMessages(sessionId, request.getMessage());
        
        // 构建流式请求
        DeepSeekRequest deepSeekRequest = DeepSeekRequest.builder()
                .messages(messages)
                .stream(true)  // 启用流式输出
                .build();
        
        String requestBody = JSON.toJSONString(deepSeekRequest);
        log.debug("DeepSeek 流式API请求: {}", requestBody);
        
        // 构建HTTP请求
        Request httpRequest = new Request.Builder()
                .url(chatConfig.getApiUrl())
                .post(RequestBody.create(requestBody, MediaType.parse("application/json")))
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " + chatConfig.getApiKey())
                .addHeader("Accept", "text/event-stream")
                .build();
        
        StringBuilder fullResponse = new StringBuilder();
        
        try (Response response = okHttpClient.newCall(httpRequest).execute()) {
            if (!response.isSuccessful()) {
                String errorBody = response.body() != null ? response.body().string() : "";
                log.error("DeepSeek 流式API请求失败，状态码: {}, 响应: {}", response.code(), errorBody);
                throw new RuntimeException("API请求失败: " + response.code());
            }
            
            if (response.body() == null) {
                throw new RuntimeException("响应体为空");
            }
            
            // 处理流式响应
            String line;
            java.io.BufferedReader reader = new java.io.BufferedReader(
                new java.io.InputStreamReader(response.body().byteStream(), StandardCharsets.UTF_8));
            
            while ((line = reader.readLine()) != null) {
                if (line.trim().isEmpty()) {
                    continue;
                }
                
                // 处理SSE格式的数据
                if (line.startsWith("data: ")) {
                    String data = line.substring(6); // 移除"data: "前缀
                    
                    // 检查是否为结束标记
                    if ("[DONE]".equals(data)) {
                        break;
                    }
                    
                    try {
                        // 解析JSON数据
                        DeepSeekStreamResponse streamResponse = JSON.parseObject(data, DeepSeekStreamResponse.class);
                        
                        if (streamResponse != null && streamResponse.getChoices() != null && 
                            !streamResponse.getChoices().isEmpty()) {
                            
                            DeepSeekStreamResponse.Choice choice = streamResponse.getChoices().get(0);
                            if (choice.getDelta() != null && choice.getDelta().getContent() != null) {
                                String content = choice.getDelta().getContent();
                                fullResponse.append(content);
                                
                                // 实时发送内容片段
                                emitter.send(SseEmitter.event()
                                    .name("data")
                                    .data(content));
                            }
                        }
                    } catch (Exception e) {
                        log.warn("解析流式响应数据失败: {}", data, e);
                    }
                }
            }
            
        } catch (IOException e) {
            log.error("处理流式响应失败", e);
            throw e;
        }
        
        return fullResponse.toString();
    }
}